package com.accounting.client.frontend.cost;

import java.util.ArrayList;
import java.util.List;

import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.cost.dialog.AddCostDialog;
import com.accounting.client.frontend.cost.dialog.UpdateCostDialog;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.CostStatus;
import com.accounting.client.remote.enumeration.Costs;
import com.accounting.client.remote.enumeration.Currency;
import com.accounting.client.remote.obj.Cost;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;

import corelib.client.NumberFormats;
import corelib.client.date.DateFormats;
import corelib.client.delegate.Action;
import corelib.client.delegate.DataCallback;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.search.PagingRequest;
import corelib.client.search.PagingResult;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.SimpleDataModel;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.dialog.SimpleDialog;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.grid.SimpleDataGrid;
import corelib.client.ui.widget.grid.SimpleDataGridHandler;
import corelib.client.ui.widget.grid.cell.CellRenderer;
import corelib.client.ui.widget.grid.column.ColumnConfig;
import corelib.client.ui.widget.grid.column.ColumnConfigs;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;
import corelib.client.ui.widget.page.PageBase;
import corelib.client.ui.widget.page.PageContext;
import corelib.client.ui.widget.panel.SimpleLayoutPanel;
import corelib.client.ui.widget.toolbar.SimpleRibbon;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton.ButtonSize;

public class CostManager extends PageBase<Widget> {
	
	private int currentOffset = 0;
	private int currentNumOfRecordsPerPage = 0;
	
	private final static int MaxRecordsPerPage = 20;
	
	private CostTableHandler costTableHandler;
	private SimpleDataGrid<Cost> costTable;
	
	private SimpleRibbon toolBar;
	private SimpleRibbonButton deleteBtn;
	private SimpleRibbonButton updateBtn;
	private SimpleRibbonButton previousBtn;
	private SimpleRibbonButton nextBtn;
	
	public CostManager(){
		setPageName("个人花费管理");
		setPageIcon(BoxResources.INSTANCE.coins24());
	}
	
	@Override
	protected Widget createWidget() {
		toolBar   = createToolBar();
		costTable = createTable();
		
		SimpleLayoutPanel layoutPanel = new SimpleLayoutPanel();
		layoutPanel.add(toolBar);
		layoutPanel.add(costTable);
		layoutPanel.setWidgetTopHeight(toolBar, 0, Unit.PX, 80, Unit.PX);
		layoutPanel.setWidgetTopBottom(costTable, 80, Unit.PX, 0, Unit.PX);
		return layoutPanel;
	}
	
	@Override
	public void onShow(PageContext pageContext) {
		super.onShow(pageContext);
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				load(currentOffset);
			}
		}, 400);
	}

	protected SimpleRibbon createToolBar(){
		SimpleRibbon toolBar = new SimpleRibbon();
		toolBar.addPushButton(new SimpleRibbonButton("增加其他费用", 
				CommonResources.INSTANCE.plus1_32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						SimpleDialog.show(new AddCostDialog(new Action(){
							@Override
							public void run() {
								load(currentOffset);
							}
						}));
					}
				}
		));
		toolBar.addPushButton(updateBtn = new SimpleRibbonButton("更新费用信息", 
				BoxResources.INSTANCE.update32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						Cost cost = costTable.getSelectedObject();
						if (cost != null) {
							SimpleDialog.show(new UpdateCostDialog(cost, new Action(){
								@Override
								public void run() {
									load(currentOffset);
								}
							}));
						}
					}
				}
		));
		toolBar.addPushButton(deleteBtn = new SimpleRibbonButton("删除费用", CommonResources.INSTANCE.delete32(), ButtonSize.Medium,
				new WidgetListener() {
				@Override
				public void valueUpdated(Widget widget) {
					final Cost cost = costTable.getSelectedObject();
					if (cost != null) {
						SimpleMessageBox.confirm("确认", "您确定要删除此项吗?",new DataCallback<Boolean>(){
							@Override
							public void onCompleted(Boolean data) {
								if (data == Boolean.TRUE){
									delete(cost);
								}
							}
						});
					}
				}
			}
	    ));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(new SimpleRibbonButton("刷新", 
				CommonResources.INSTANCE.refresh32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						load(currentOffset);
					}
				}
		));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(previousBtn = new SimpleRibbonButton("前页", 
				CommonResources.INSTANCE.prev32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						load(Math.max(currentOffset - MaxRecordsPerPage, 0));
					}
				}
		));
		toolBar.addPushButton(nextBtn = new SimpleRibbonButton("后页", 
				CommonResources.INSTANCE.next32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						load(Math.max(currentOffset + MaxRecordsPerPage, 0));
					}
				}
		));
		updateBtn.setEnabled(false);
		deleteBtn.setEnabled(false);
		previousBtn.setEnabled(false);
		nextBtn.setEnabled(false);
		return toolBar;
	}
	
	private void load(int offset){
		SimpleModal.show("Loading...");
		PagingRequest request = new PagingRequest();
		request.setOffset(0);
		request.setLimit(MaxRecordsPerPage);
		String passport = SessionManager.getPassport();
		Services.CostService.ListCosts(passport, request, new AsyncCallback<PagingResult<Cost>>(){
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
			    ErrorHandler.handleServiceError(caught);
			}
			
			@Override
			public void onSuccess(PagingResult<Cost> result) {
				SimpleModal.hide();
				currentOffset = result.getOffset();
				currentNumOfRecordsPerPage = result.getData().size();
				costTableHandler.setObjects(result.getData());
				previousBtn.setEnabled(currentOffset >0);
				nextBtn.setEnabled(currentOffset + currentNumOfRecordsPerPage < result.getTotal());
				deleteBtn.setEnabled(false);
				updateBtn.setEnabled(false);
			}
		});
	}
	
	private void delete(Cost cost){
		SimpleModal.show("努力删除中。。。");
		String passport = SessionManager.getPassport();
		Services.CostService.RemoveCost(passport, cost.getId(), new AsyncCallback<Boolean>(){
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
				ErrorHandler.handleServiceError(caught);
			}

			@Override
			public void onSuccess(Boolean result) {
				if (result == Boolean.TRUE){
					SimpleModal.hide();
					load(currentOffset);
				}
			}
		});
	}
	
	protected SimpleDataGrid<Cost> createTable(){
		return new SimpleDataGrid<Cost>(MaxRecordsPerPage, costTableHandler = new CostTableHandler());
	}
	
	private class StatusRenderer extends CellRenderer<Cost> {
		@Override
		public void render(SimpleDataModel<Cost> model,
				ColumnConfig columnConfig, int rowIndex, int colIndex,
				SafeHtmlBuilder sb) {
			Cost cost = model.getObject();
			if (cost.getStatus() == CostStatus.NotProcessed){
				sb.append(SimpleLabel.createWarnning(CostStatus.Not_Processed.getName()).asSafeHtml());	
			}
			else if (cost.getStatus() == CostStatus.CheckedOut){
				sb.append(SimpleLabel.createSuccess(CostStatus.CHECKED_OUT.getName()).asSafeHtml());
			}
		}
	}
	
	private class AmountRenderer extends CellRenderer<Cost> {
		@Override
		public void render(SimpleDataModel<Cost> model,
				ColumnConfig columnConfig, int rowIndex, int colIndex,
				SafeHtmlBuilder sb) {
			Cost cost = model.getObject();
			if (cost.getCurrency().equals(Currency.AUD.getName())){
				sb.appendHtmlConstant(NumberFormats.AUD.format(cost.getAmount()));	
			}
			else if (cost.getCurrency().equals(Currency.RMB.getName())){
				sb.appendHtmlConstant(NumberFormats.RMB.format(cost.getAmount()));	
			}
		}
	}
	
	private final class CostTableHandler extends SimpleDataGridHandler<Cost> {
		
		private final static String Type 		= "Type";
		private final static String Amount		= "Amount";
		private final static String Description	= "Description";
		private final static String User  		= "User";
		private final static String Date 		= "Date";
		private final static String Status      = "Status";
		private List<Cost> data;
		
		@Override
		public List<ColumnConfig> createColumns() {
			List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
			configs.add(ColumnConfigs.create(Date, 		  "创建时间",  70, DateFormats.YYYY_MM_DD));
			configs.add(ColumnConfigs.create(User, 		  "创建人",   70));
			configs.add(ColumnConfigs.create(Type, 		  "类型",    100));
			configs.add(ColumnConfigs.create(Status,	  "状态",    50,  new StatusRenderer()));
			configs.add(ColumnConfigs.create(Amount,	  "金额",    100, new AmountRenderer()));
			configs.add(ColumnConfigs.create(Description, "描述",    100));
			return configs;
		}

		@Override
		public void format(int index, SimpleDataModel<Cost> model) {
			Cost cost = model.getObject();
			model.set(Date, 	   cost.getDateCreated());
			model.set(Type, 	   Costs.GetCName(cost.getType()));
			model.set(Status, 	   cost.getStatus());
			model.set(Description, cost.getDescription());
			model.set(User, 	   ApplicationContext.getUser(cost.getUserId()).getCName());
			model.set(Amount, 	   cost.getAmount());
		}
		
		public void setObjects(List<Cost> objects){
			CostTableHandler.this.data = objects;
			this.getGrid().setObjects(objects);
		}
		
		@Override
		public List<Cost> getObjects() {
			return CostTableHandler.this.data;
		}

		@Override
		public void onObjectClicked(Cost obj) {
			if (obj != null){
				deleteBtn.setEnabled(true);
				updateBtn.setEnabled(true);
			}
		}

		@Override
		public void onObjectDoubleClicked(Cost obj) {
			onObjectClicked(obj);
		}
		
	}
}
